﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;

using System.IO;
using System.Globalization;

namespace Geoconcepts.SocialServices
{
    /// <summary>
    /// Encapsules Geonames API functionality. 
    /// http://www.geonames.org/export/ws-overview.html
    /// </summary>
    public class Geonames
    {
        #region GetGeonamesFullSchema
        /// <summary>
        /// Realiza una consulta genérica a Geonames y guarda el XSD schema en el fichero
        /// pasado por parámetro.
        /// </summary>
        /// <param name="strSchemaPath"></param>
        /// <returns></returns>
        private DataSet GetGeonamesFullSchema(string strSchemaPath)
        {
            DataSet dtsGeonames = new DataSet();
            CultureInfo ciEnglish = new CultureInfo("en-US", true);
            String strTempFilePath = System.IO.Path.GetTempFileName();

            WebClient webCliente = new WebClient();
            webCliente.Encoding = Encoding.UTF8;

            try
            {
                #region Si nos conectamos con el proxy01, ponemos la clave
                WebProxy proxyDefault = (WebProxy)WebProxy.GetDefaultProxy();

                if (proxyDefault.Address != null && proxyDefault.Address.Host == "proxy01")
                {
                    WebProxy webProxy01 = new WebProxy("proxy01:8080", true);
                    webProxy01.Credentials = new NetworkCredential("accesointernet", "gobnavarra", "admon-cfnavarra");
                    webCliente.Proxy = webProxy01;
                }
                #endregion Si nos conectamos con el proxy01, ponemos la clave

                #region Realizamos una consulta genérica para obtener el XSD de la respuesta de Geonames
                string sUrl = "http://ws.geonames.org/search?q=glasgow&maxRows=10&style=FULL&country=GB&featureClass=P";
                string strResponse = "";

                strResponse = webCliente.DownloadString(sUrl);
                #endregion Realizamos una consulta genérica para obtener el XSD de la respuesta de Geonames

                #region Guardamos el Schema del XML recibido
                XmlDocument xmlGeonamesResponse = new XmlDocument();
                xmlGeonamesResponse.LoadXml(strResponse);
                xmlGeonamesResponse.Save(strTempFilePath);

                dtsGeonames.ReadXml(strTempFilePath);
                dtsGeonames.WriteXmlSchema(strSchemaPath);
                #endregion Guardamos el Schema del XML recibido

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                File.Delete(strTempFilePath);
            }
        }
        #endregion GetGeonamesFullSchema

        #region GeonamesFullResponse

        /// <summary>
        /// Retrieves the most relevant feature for the strName query in any Country
        /// It returns FULL Geonames XML information
        /// </summary>
        /// <param name="strName">Query name</param>
        /// <returns></returns>
        public GeonamesFullResponse GeonamesFullSearch(string strName)
        {
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                string strCountry = "";
                dtsGeonames = GeonamesFullSearch(strName, strCountry);

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// Retrieves the most relevant feature for the strName query in strCountry
        /// It returns FULL Geonames XML information
        /// </summary>
        /// <param name="strName">Query name</param>
        /// <param name="strCountry">ISO-636 2-letter language code</param>
        /// <returns></returns>
        public GeonamesFullResponse GeonamesFullSearch(string strName, string strCountry)
        {
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                string strFeatureClass = "";
                dtsGeonames = GeonamesFullSearch(strName, strCountry, strFeatureClass);

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// Retrieves the most relevant feature for the strName query in strCountry with strFeatureClass
        /// It returns FULL Geonames XML information
        /// </summary>
        /// <param name="strName">Query name</param>
        /// <param name="strCountry">ISO-636 2-letter language code</param>
        /// <param name="strFeatureClass">Geonames Feature Class Code</param>
        /// <returns></returns>
        public GeonamesFullResponse GeonamesFullSearch(string strName, string strCountry, string strFeatureClass)
        {
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                string strFeatureCode = "";
                dtsGeonames = GeonamesFullSearch(strName, strCountry, strFeatureClass, strFeatureCode);

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// Retrieves the most relevant feature for the strName query in strCountry with strFeatureClass and strFeatureCode
        /// It returns FULL Geonames XML information
        /// </summary>
        /// <param name="strName">Query name</param>
        /// <param name="strCountry">ISO-636 2-letter language code</param>
        /// <param name="strFeatureClass">Geonames Feature Class Code</param>
        /// <param name="strFeatureCode">Geonames Feature Code</param>
        /// <returns></returns>
        public GeonamesFullResponse GeonamesFullSearch(string strName, string strCountry, string strFeatureClass, string strFeatureCode)
        {
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                string strStyle = "FULL";
                int nMaxRows = 1;

                dtsGeonames = GeonamesFullSearch(strName, nMaxRows, strCountry, strFeatureClass, strFeatureCode, strStyle);

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// Retrieves the most relevant feature for the strName query in strCountry with strFeatureClass and strFeatureCode and strStyle level
        /// strLevel can be: SHORT, MEDIUM, LONG, FULL
        /// </summary>
        /// <param name="strName"></param>
        /// <param name="nMaxRows"></param>
        /// <param name="strCountry"></param>
        /// <param name="strFeatureClass"></param>
        /// <param name="strFeatureCode"></param>
        /// <param name="strStyle"></param>
        /// <returns></returns>
        public GeonamesFullResponse GeonamesFullSearch(string strName, int nMaxRows, string strCountry, string strFeatureClass, string strFeatureCode, string strStyle)
        {
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();
            CultureInfo ciEnglish = new CultureInfo("en-US", true);

            WebClient webCliente = new WebClient();
            webCliente.Encoding = Encoding.UTF8;

            try
            {
                #region Si nos conectamos con el proxy01, ponemos la clave
                WebProxy proxyDefault = (WebProxy)WebProxy.GetDefaultProxy();

                if (proxyDefault.Address != null && proxyDefault.Address.Host == "proxy01")
                {
                    WebProxy webProxy01 = new WebProxy("proxy01:8080", true);
                    webProxy01.Credentials = new NetworkCredential("accesointernet", "gobnavarra", "admon-cfnavarra");
                    webCliente.Proxy = webProxy01;
                }
                #endregion Si nos conectamos con el proxy01, ponemos la clave

                #region Realizamos la consulta a Geonames
                string sUrl = "http://ws.geonames.org/search?q=" + strName + "&maxRows=" + nMaxRows.ToString();

                if (strCountry != "")
                    sUrl += "&country=" + strCountry;

                if (strFeatureClass != "")
                    sUrl += "&featureClass=" + strFeatureClass;

                if (strFeatureCode != "")
                    sUrl += "&featureCode=" + strFeatureCode;

                if (strStyle != "")
                    sUrl += "&style=" + strStyle;

                string strResponse = "";

                strResponse = webCliente.DownloadString(sUrl);
                #endregion Realizamos la consulta a Geonames

                #region Guardamos en el Dataset la respuesta de Geonames
                MemoryStream memStream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(strResponse));

                XmlTextReader xmlTextReader = new XmlTextReader(memStream);

                dtsGeonames.ReadXml(xmlTextReader, XmlReadMode.InferTypedSchema);

                memStream.Close();
                xmlTextReader.Close();
                #endregion Guardamos en el Dataset la respuesta de Geonames

                return dtsGeonames;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }
        #endregion GeonamesFullResponse

        /// <summary>
        /// Returns strName alternate Names by Geonames Web Services
        /// </summary>
        /// <param name="strName">Geographic Name</param>
        /// <param name="strCountry">ISO country code</param>
        /// <returns></returns>
        public string GeonamesGetAlternateNames(string strName, string strCountry)
        {
            string strResult = "";
            string[] strComa = new string[1];
            strComa[0] = ",";
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                dtsGeonames = GeonamesFullSearch(strName, strCountry);

                if (dtsGeonames != null && dtsGeonames.geoname.Count > 0)
                {
                    strResult = dtsGeonames.geoname[0].alternateNames;
                }

                return strResult;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// Returns strName alternate Names by Geonames Web Services, and all administrative superior regions
        /// for instance, province, country, etc.
        /// </summary>
        /// <param name="strName">Geographic Name</param>
        /// <param name="strCountry">ISO country code</param>
        /// <returns></returns>
        public string GeonamesGetAllAdministrativeAlternateNames(string strName, string strCountry)
        {
            string strResult = "";
            string[] strComa = new string[1];
            strComa[0] = ",";
            GeonamesFullResponse dtsGeonames = new GeonamesFullResponse();

            try
            {
                dtsGeonames = GeonamesFullSearch(strName, strCountry);

                if (dtsGeonames != null && dtsGeonames.geoname.Count > 0)
                {
                    strResult = dtsGeonames.geoname[0].alternateNames;

                    if (!dtsGeonames.geoname[0].IsadminName1Null())
                    {
                        string strAdmin1AlternateNames = GeonamesGetAlternateNames(dtsGeonames.geoname[0].adminName1, strCountry);
                        if (strAdmin1AlternateNames != "")
                            strResult = strResult + "," + strAdmin1AlternateNames;
                    }

                    if (!dtsGeonames.geoname[0].IsadminName2Null())
                    {
                        string strAdmin2AlternateNames = GeonamesGetAlternateNames(dtsGeonames.geoname[0].adminName2, strCountry);
                        if (strAdmin2AlternateNames != "")
                            strResult = strResult + "," + strAdmin2AlternateNames;
                    }

                    if (!dtsGeonames.geoname[0].IscountryNameNull())
                    {
                        string strCountryAlternateNames = GeonamesGetAlternateNames(dtsGeonames.geoname[0].countryName, strCountry);
                        if (strCountryAlternateNames != "")
                            strResult = strResult + "," + strCountryAlternateNames;
                    }
                }

                return strResult;
            }
            catch (System.Net.WebException netEx)
            {
                return strName;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }
    }
}
